#include <glf/config.h>

#include <glf/core/str.h>
#include <glf/core/assert.hpp>


#include <malloc.h> //for _alloca

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#undef alloca

namespace glf {

void* alloca(size_t size)
{
	return _alloca(size);
}

void Breakpoint()
{
	__debugbreak();
}

} //namespace glf

#ifndef PLATFORM_OSP

#include <windows.h>

namespace glf {

#ifndef GLF_PLATFORM_WP8

__declspec(thread) HHOOK gCustomMessageBoxHook ;

LRESULT CALLBACK CustomMessageBoxProc(INT nCode, WPARAM wParam, LPARAM lParam) {
	// notification that a window is about to be activated
	// window handle is wParam
	if (nCode == HCBT_ACTIVATE) {
		// set window handles
		HWND hChildWnd = (HWND)wParam;
		//to get the text of the Yes button
		UINT result;
		if(GetDlgItem(hChildWnd, IDCANCEL)) {
			result = SetDlgItemTextA(hChildWnd, IDCANCEL, "break");
		}
		if(GetDlgItem(hChildWnd, IDTRYAGAIN)) {
			result = SetDlgItemTextA(hChildWnd, IDTRYAGAIN, "ignore");
		}
		if(GetDlgItem(hChildWnd, IDCONTINUE)) {
			result = SetDlgItemTextA(hChildWnd, IDCONTINUE, "continue");
		}
		//Continue changing other button captions

		// exit CBT hook
		UnhookWindowsHookEx(gCustomMessageBoxHook);
	}
	// otherwise, continue with any possible chained hooks
	else {
		CallNextHookEx(gCustomMessageBoxHook, nCode, wParam, lParam);
	}
	return 0;
}

int CustomMessageBox(HWND hwnd, const char* lpText, const char* lpCaption, UINT uType) {
	gCustomMessageBoxHook = SetWindowsHookEx(WH_CBT, &CustomMessageBoxProc, 0, GetCurrentThreadId());
	return MessageBoxA(hwnd, lpText, lpCaption, uType);
}

#endif // #ifndef GLF_PLATFORM_WP8

AssertBehavior Assert(const char *file, int line, const char *fmt, ... ) {
	
	char caption[256];
	Sprintf_s(caption, "assert failed at: %s(%d)", file, line);

	va_list args;
	va_start(args, fmt);

	char buffer[1024];
	Vsnprintf(buffer, fmt, args);

	const char* msgBox = "\n"
		"Press BREAK to debug\n" 
		"Press IGNORE to never see this assert again\n"
		"or Press CONTINUE";

	Strcat_s(buffer, msgBox);

	//TODO: make messagebox with 4 buttons
	// 1 quit
	// 2 ignore this time
	// 3 ignore forever
	// 4 debug
#if GLF_PLATFORM_WP8
#	ifdef _UNICODE
	std::string msg(buffer);
	std::wstring wmsg(msg.begin(), msg.end());
	OutputDebugString(wmsg.c_str());
#	else
	OutputDebugString(buffer);
#	endif
	int value = IDRETRY;
#else
	int value = CustomMessageBox(0, buffer, caption, MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE);
#endif

	if(value == IDCANCEL)
	{
		return ASSERT_BREAK;
	}
	else if(value == IDTRYAGAIN)
	{
		return ASSERT_IGNORE_ALWAYS;
	}
	else //if(value == IDCONTINUE)
	{
		return ASSERT_IGNORE_THIS_TIME;
	}
}

}

#else

namespace glf {
AssertBehavior Assert(const char *file, int line, const char *fmt, ... ) {
	__debugbreak();
	return ASSERT_IGNORE_ALWAYS;
}
}


#endif
